package com.example.security;

import java.security.Key;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.UnsupportedJwtException;
import io.jsonwebtoken.security.Keys;

@Component
public class JwtUtils {
    private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class);

    @Value("${jwt.secret}")
    private String jwtSecret;

    @Value("${jwt.expiration}")
    private int jwtExpirationMs;

    private Key getSigningKey() {
        // 如果密钥不够长，使用Keys工具类生成安全的密钥
        try {
            return Keys.hmacShaKeyFor(jwtSecret.getBytes());
        } catch (Exception e) {
            logger.warn("Using default secure key as configured key is not strong enough");
            // 生成安全的HS512密钥
            return Keys.secretKeyFor(SignatureAlgorithm.HS512);
        }
    }

    public String generateJwtToken(Authentication authentication) {
        UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal();
        Key key = getSigningKey();

        // 获取角色并进行压缩（使用简短的角色标识符）
        List<String> compressedRoles = userPrincipal.getAuthorities().stream()
                .map(authority -> {
                    String role = authority.getAuthority();
                    // 压缩角色名称："ROLE_TEACHER" -> "T", "ROLE_ADMIN" -> "A", "ROLE_STUDENT" -> "S"
                    if (role.equals("ROLE_TEACHER")) return "T";
                    if (role.equals("ROLE_ADMIN")) return "A";
                    if (role.equals("ROLE_STUDENT")) return "S";
                    if (role.equals("ROLE_MODERATOR")) return "M";
                    return role; // 对于其他角色保留原样
                })
                .collect(Collectors.toList());

        // 使用HS256算法代替HS512，生成更短的签名
        return Jwts.builder()
                .setSubject((userPrincipal.getUsername()))
                .setIssuedAt(new Date())
                .setExpiration(new Date((new Date()).getTime() + jwtExpirationMs))
                .setId(UUID.randomUUID().toString())
                .claim("uid", userPrincipal.getId()) // 使用更短的字段名
                .claim("roles", compressedRoles) // 存储压缩角色
                .signWith(key, SignatureAlgorithm.HS256) // 使用HS256而不是HS512
                .compact();
    }

    public String getUserNameFromJwtToken(String token) {
        Key key = getSigningKey();
        return Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token)
                .getBody()
                .getSubject();
    }

    public Long getUserIdFromJwtToken(String token) {
        Key key = getSigningKey();
        Claims claims = Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token)
                .getBody();
        return claims.get("userId", Long.class);
    }

    public String getTokenId(String token) {
        Key key = getSigningKey();
        Claims claims = Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token)
                .getBody();
        return claims.getId();
    }

    public boolean validateJwtToken(String authToken) {
        try {
            Key key = getSigningKey();
            Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(authToken);
            return true;
        } catch (SecurityException e) {
            logger.error("Invalid JWT signature: {}", e.getMessage());
        } catch (MalformedJwtException e) {
            logger.error("Invalid JWT token: {}", e.getMessage());
        } catch (ExpiredJwtException e) {
            logger.error("JWT token is expired: {}", e.getMessage());
        } catch (UnsupportedJwtException e) {
            logger.error("JWT token is unsupported: {}", e.getMessage());
        } catch (IllegalArgumentException e) {
            logger.error("JWT claims string is empty: {}", e.getMessage());
        }

        return false;
    }

    public List<String> getRolesFromJwtToken(String token) {
        try {
            Key key = getSigningKey();
            Claims claims = Jwts.parserBuilder()
                    .setSigningKey(key)
                    .build()
                    .parseClaimsJws(token)
                    .getBody();
            
            List<String> compressedRoles = claims.get("roles", List.class);
            if (compressedRoles == null) {
                return null;
            }
            
            // 将压缩角色转换回完整角色名称
            return compressedRoles.stream()
                    .map(role -> {
                        if ("T".equals(role)) return "ROLE_TEACHER";
                        if ("A".equals(role)) return "ROLE_ADMIN";
                        if ("S".equals(role)) return "ROLE_STUDENT";
                        if ("M".equals(role)) return "ROLE_MODERATOR";
                        return role.startsWith("ROLE_") ? role : "ROLE_" + role;
                    })
                    .collect(Collectors.toList());
        } catch (Exception e) {
            logger.error("从JWT令牌获取角色失败: {}", e.getMessage());
            return Collections.emptyList();
        }
    }
}